package com.ysx.filter;

import com.alibaba.fastjson.JSON;
import com.ysx.common.constants.SystemConstants;
import com.ysx.common.pojo.TokenJsonVo;
import com.ysx.common.pojo.TokenRole;
import com.ysx.common.pojo.UserTokenInfoExp;
import com.ysx.common.utils.AppJwtUtil;
import com.ysx.common.utils.JwtToutiaoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit;

/**
 * 自定义全局过滤器(模拟登录校验token token携带方式采用get地址栏的方式)
 */
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    //做具体的逻辑操作
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //1,判断请求路径中是否包含登录或者注册 有则放行
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        String uri = request.getURI().toString();
        if (!StringUtils.isEmpty(uri) && (uri.contains("/admin/login") || uri.contains("/admin/register"))||uri.endsWith("v2/api-docs")) {
           return   chain.filter(exchange);
        }
        //2,没有 获取请求头的信息 判断是否存在token 有则继续
        String token = request.getHeaders().getFirst("accessToken");
        if (StringUtils.isEmpty(token)) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        /*//3,根据token信息 调用jjwt方法 判断token状态 通过则继续
        int tokenStatus = AppJwtUtil.verifyToken(token);
        if(tokenStatus!= SystemConstants.JWT_OK){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }*/

        //获取令牌
        UserTokenInfoExp tokenInfoExp = JwtToutiaoUtil.parseJwtUserToken(token);
        //校验错误
        if (tokenInfoExp == null) {
            //返回错误状态码
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        if (!JwtToutiaoUtil.isValidRole(token, TokenRole.ROLE_ADMIN)) {
            //返回错误状态码
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        Long userId = tokenInfoExp.getUserId();

        String tokenFromRedis = redisTemplate.opsForValue().get(SystemConstants.REDIS_TOKEN_ADMIN_PREFIX + userId);

        if (tokenFromRedis == null) {
            //redis中也过期了
            //返回错误状态码
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
       if (!tokenFromRedis.equals(token)) {
            //返回错误状态码
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        //过期--->
        if (tokenInfoExp.getExp() <  Instant.now().toEpochMilli()/1000) {
            //校验刷新令牌
            String tokenRefresh = request.getHeaders().getFirst("refreshToken");
            UserTokenInfoExp tokenInfoExp1 = JwtToutiaoUtil.parseJwtUserToken(tokenRefresh);
            if (tokenInfoExp1 == null) {
                //返回错误状态码
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
            //校验刷新令牌
            if (tokenInfoExp1.getExp()< Instant.now().toEpochMilli()/1000) {
                //返回错误状态码
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
            TokenJsonVo tokenJsonVo = JwtToutiaoUtil.createToken(tokenInfoExp);
            //存储到redis中  key: userId
            redisTemplate.opsForValue().set(
                    SystemConstants.REDIS_TOKEN_ADMIN_PREFIX+tokenInfoExp.getUserId(),
                    tokenJsonVo.getAccessToken(),JwtToutiaoUtil.TOKEN_TIME_OUT*5, TimeUnit.SECONDS);

            //设置到响应头中
            response.getHeaders().set("token", JSON.toJSONString(tokenJsonVo));
        }
        //4,路由到微服务
        return chain.filter(exchange);
    }
    //设置过滤器级别 数字越小级别越高
    @Override
    public int getOrder() {
        return -1;
    }
}